﻿using System.Windows.Data;
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Specialized;
using SwiftMVVM.ChangeTracking;
using System.Linq;
using System.ComponentModel;

namespace SwiftMVVM.ValueConverters
{
    /// <summary>
    /// Converts the DeltaList on a change manager into a list
    /// </summary>
    public class DeltaListToStringConverter : IValueConverter
    {
        /// <summary>
        /// Allow the user to put in a 'Friendly' description on
        /// any object via the Description attribute
        /// </summary>
        /// <param name="type"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        private static string ResolveDescription(Type type)
        {
            return ((DescriptionAttribute[])type.GetCustomAttributes(typeof(DescriptionAttribute), true))
                .Select(da => da.Description).FirstOrDefault() ?? type.Name;
        }

        /// <summary>
        /// Returns the object description by taking the value of the 
        /// description attribute ([Description("MyID")] and
        /// formatting it with the value the attribute decorates
        /// </summary>
        /// <param name="item"></param>
        /// <returns>MyID: 2343</returns>
        private static string GetObjectDescription(object item)
        {
            return item.GetType().GetProperties()
                .Select(pi => new { PropertyInfo = pi, Descriptions = (DescriptionAttribute[])pi.GetCustomAttributes(typeof(DescriptionAttribute), true) })
                .Where(pd => pd.Descriptions != null && pd.Descriptions.Length == 1)
                .Select(pd => string.Format("{0}: {1}", (pd.Descriptions[0]).Description, pd.PropertyInfo.GetValue(item, null)))
                .FirstOrDefault();
        }

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var stringBuilder = new StringBuilder();
            var deltaList = value as IEnumerable<ChangeDetail>;
            if (deltaList != null)
            {
                foreach (var differential in deltaList)
                {
                    //We log things just a little different depending on whether or not 
                    //this is a collection we're tracking
                    if (differential.ObjectThatChanged is INotifyCollectionChanged) 
                    {
                        stringBuilder.AppendLine(string.Format("{0} {1} {2} {3} {4}",
                            differential.PriorValue, ResolveDescription(differential.Value.GetType()),
                            GetObjectDescription(differential.Value) ?? "New",
                            ((string)differential.PriorValue) == "Added" ? "to" : "from",
                            differential.Property));
                    }
                    else
                    {
                        stringBuilder.AppendLine(string.Format("{0} {1}: Changed {2}, From {3} to {4}",
                            ResolveDescription(differential.ObjectThatChanged.GetType()),
                            GetObjectDescription(differential.ObjectThatChanged) ?? "New",
                            differential.Property, differential.PriorValue, differential.Value));
                    }
                }
            }

            return stringBuilder.ToString();
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}
